﻿using Abp.Zero.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using NetCore.Authorization.Roles;
using NetCore.Authorization.Users;
using NetCore.Entities.LocationAreas;
using NetCore.Entities.Needs;
using NetCore.Entities.Organizations;
using NetCore.Entities.Projects;
using NetCore.Entities.System;
using NetCore.MultiTenancy;
using System.Linq;

namespace NetCore.EntityFrameworkCore
{
    //[AutoRepositoryTypes(
    //    typeof(IRepository<>),
    //    typeof(IRepository<,>),
    //    typeof(NetCoreRepositoryBase<>),
    //    typeof(NetCoreRepositoryBase<,>),
    //    WithDefaultRepositoryInterfaces = true
    //)]//仅用于重写IRepository里的方法而不提供新的接口的时候使用，如果要添加新的查询或者插入数据功能应在模块启动时依赖注入自定义的泛型接口
    public class NetCoreDbContext : AbpZeroDbContext<Tenant, Role, User, NetCoreDbContext>
    {
        /* Define a DbSet for each entity of the application */

        public NetCoreDbContext(DbContextOptions<NetCoreDbContext> options)
            : base(options)
        {
            //DbContext 是个上下文环境，里面内置对象跟踪，会开启连接 就等于一个数据库连接
            //一次请求，最好是一个context;多个请求/多线程最好是多个实例；用完尽快释放
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //https://github.com/aspnet/EntityFrameworkCore 
            //optionsBuilder.UseLazyLoadingProxies();//启用懒加载，netcore下一个版本才会支持?
            optionsBuilder.EnableSensitiveDataLogging();//启用sql日志
            base.OnConfiguring(optionsBuilder);
        }

        #region 模型数据库映射 统一问题解决 联合唯一索引 decimal小数位数控制
        /// <summary>
        /// 模型数据库映射
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>()
                .Ignore(m => m.DeleterUser)
                .OwnsOne(x => x.Address);

            modelBuilder.Entity<Project>()
                .OwnsOne(m => m.Address);
            modelBuilder.Entity<Organization>()
                .OwnsOne(m => m.Address);

            //建联合唯一索引
            modelBuilder.Entity<Organization>()
                .HasIndex(m => new { m.Code, m.Name, m.OrganizationType })
                .IsUnique();

            ////modelBuilder.Model.RemoveEntityType(nameof(AuditLog));
            ////modelBuilder.Ignore<AuditLog>();//可以忽略某个实体不生成到数据库

            //ef可以自己解析
            //modelBuilder.Entity<Organization>().HasOne(n => n.Parent);
            //modelBuilder.Entity<Organization>().HasMany(m => m.Children);

            #region decimal小数位数控制 财务系统保存数据系统统一使用decimal
            ////单个字段小数位数控制
            ////modelBuilder.Entity<Project>().Property(m => m.Price).HasColumnType("decimal(27,9)");
            var properties = modelBuilder.Model.GetEntityTypes().SelectMany(x => x.GetProperties())
                .Where(x => x.ClrType == typeof(decimal) || x.ClrType == typeof(decimal?));
            foreach (var property in properties)
            {
                property.Relational().ColumnType = "decimal(27, 9)";
            }

            #endregion
        }
        #endregion

        #region 实体集(NetCore属性名称对应表名)
        /// <summary>
        /// 公司表
        /// </summary>
        public DbSet<Organization> Organizations { get; set; }
        /// <summary>
        /// 岗位用户表
        /// </summary>
        public DbSet<OrganizationUser> OrganizationUsers { get; set; }
        /// <summary>
        /// 项目表
        /// </summary>
        public DbSet<Project> Projects { get; set; }
        /// <summary>
        /// 项目用户表
        /// </summary>
        public DbSet<ProjectUser> ProjectUsers { get; set; }
        /// <summary>
        /// 项目附件表
        /// </summary>
        public DbSet<ProjectAttachment> ProjectAttachments { get; set; }
        /// <summary>
        /// 需求表
        /// </summary>
        public DbSet<Need> Needs { get; set; }
        /// <summary>
        /// 需求附件表
        /// </summary>
        public DbSet<NeedAttachment> NeedAttachments { get; set; }
        /// <summary>
        /// 位置区域（全国省市区城乡等区域代码位置信息）
        /// </summary>
        public DbSet<LocationArea> LocationAreas { get; set; }
        /// <summary>
        /// 位置区域（全国省市区城乡等区域代码位置信息）
        /// </summary>
        public DbSet<Notify> Notifies { get; set; }
        #endregion
    }
}
